#!/usr/bin/envpython
# -*-coding:UTF-8-*-
'''
@File    :   rest_router_with_decorater.py
@Contact :   308711822@qq.com
@License :   (C) Copyright 2021-2225, Personal exclusive right.

@Modify Time      @Author    @Version    @Desciption
------------      -------    --------    -----------
2023/2/4 16:28   小钟同学      1.0         None
'''
from enum import Enum
from typing import (
    List,
    Optional,
    Sequence,
    Union, Callable, Any,
)

from fastapi import params, APIRouter
from pydantic.typing import AnyCallable
from starlette.routing import Mount as Mount  # noqa

from infirmary_admin_src.infirmary_common.infirmary_controller import IBaseController
from infirmary_admin_src.infirmary_common.infirmary_service.base import IService


def RestControllerApi(path_prefix: str = ""):
    def back(cls):
        cls.path_prefix = path_prefix  # 给类添加属性
        return cls

    return back


def RestControllerInject(dependencies: Optional[Sequence[params.Depends]] = None):
    def back(cls):
        cls.dependencies = dependencies  # 给类添加属性
        return cls

    return back


# class RestControllerDecrator:
#     def __init__(self, cls):  # 传送的是cls类
#         self.cls = cls
#         print('函数调用cls222',self.cls)
#
#     def __call__(self, *args, **kwargs):  # 接受任意参数
#         # print('函数调用cls',self.cls)
#         # sadadas =self.cls.instance()  # 适应test的任意参数
#         print('函数调用cls222')
#         pass
#         return self.cls


def RestServiceInject(service: Optional[IService] = None):
    def back(cls):
        cls.service = service  # 给类添加属性
        return cls

    return back


def RestDocumentApi(
        tags: Optional[List[Union[str, Enum]]] = None,
        redirect_slashes: bool = True,
        deprecated: Optional[bool] = None,
        include_in_schema: bool = True):
    def back(cls):
        cls.tags = tags  # 给类添加属性
        cls.redirect_slashes = redirect_slashes  # 给类添加属性
        cls.deprecated = deprecated  # 给类添加属性
        cls.include_in_schema = include_in_schema  # 给类添加属性
        return cls

    return back


def RestInjectAPIRouter(prefix, tags, *args, **kwargs):
    def back(cls):

        if not hasattr(cls, 'router_api'):
            _endpointsaaaa: List[Callable] = []
            cls._endpointsaaaa = _endpointsaaaa
            cls.router = APIRouter(*args, **kwargs)
            import inspect
            # inspect.isfunction(getattr(cls, i))])
            for i in dir(cls):
                if inspect.isfunction(getattr(cls, i)) and hasattr(getattr(cls, i), '_endpoint'):
                    cls.router.add_api_route(path='/sss', endpoint=getattr(cls, i))
        else:
            pass

        return cls

    return back


import asyncio
from asyncio import iscoroutinefunction
from functools import partial
from starlette.concurrency import run_in_threadpool


def wrapper_record_background_task(func):
    '''
    基于装饰的方式获取被装饰的类方法中指定的self本身的对象，这样可以已插件的方式处理额外的任务,
    该装饰器可以获取到类中的request对象，进而获取对应的app对象其他对象，然后执行相关异步任务的操作
    :param func:
    :return:
    '''
    if iscoroutinefunction(func):
        async def wrapper(self: IBaseController, *args, **kwargs):
            if self and getattr(self, 'request'):
                pass
                # aiojobs = self.request.app.aiojobs
                # await aiojobs.spawn(task_record_login.background_task(2))
                # await aiojobs.spawn(task_record_updata_login.background_task(3))
            return await func(self, *args, **kwargs)

        return wrapper
    else:
        def wrapper(self, *args, **kwargs):
            aiojobs = self.request.app.aiojobs
            # 需注意asgiref处理此类异步任务会有问题，还是得用大佬自己写的
            # async_to_sync(aiojobs.spawn)(task_record_login.background_task(1))
            # async_to_sync(aiojobs.spawn)(task_record_updata_login.background_task(2))
            # aiojobs.spawn(task_record_login.background_task(15))
            # aiojobs.spawn(task_record_updata_login.background_task(15))
            # 设计异步任务和同步任务的转换
            from asyncer import syncify
            # syncify(async_function=aiojobs.spawn)(task_record_login.background_task(1))
            # syncify(async_function=aiojobs.spawn)(task_record_updata_login.background_task(15))
            return func(self, *args, **kwargs)

        return wrapper



